package SM::Server::GameLogic;

use strict;
use warnings;

use SM::Constants;

use Data::Dumper::Simple;
use Module::Load;

sub initialize_client {
	my ($arg_ref) = @_;
	my $username  = $arg_ref->{username};
	my $password  = $arg_ref->{password};
	my $client    = $arg_ref->{client};
	my $packet;

	# TODO: Add password checking!

	# Create the SM::Server::Client object
	# If there is another user with the same name just remove them from the game
	# This would happen if they disconnected suddenly, etc
	# TODO: Add something that keeps track of the clients a client knows about
	if ( exists $SM::Server::clients{$username} ) {
		delete $SM::Server::clients{$username};
	}

	$SM::Server::clients{$username} = SM::Server::Client->new(
		{ username => $username, session_id => $client, } );

	# Send the Location::Initial packet
	$packet = SM::Server::Packet::Out::Avatar::Initial->new(
		{   x => $SM::Server::clients{$username}->{location}{x},
			y => $SM::Server::clients{$username}->{location}{y},
		}
	);
	SM::Server->send_packet( $client, $packet->get_raw_data() );
	
	# Fix the WTF here: why wont this work?
	SM::Server->set_client_alias( $client, $username );

	# Send all the other users the new player's data
	broadcast_location_updates($username);

	# Send the new client everything they need to know
	SEND_UPDATE_PACKET:
	foreach my $player ( keys %SM::Server::clients ) {    
		if ( $player eq $username ) {
			next SEND_UPDATE_PACKET;
		}

	# If there are in the same area, send a packet letting the client know they exist
	#TODO: Not this!
		my $packet = SM::Server::Packet::Out::Avatar::Location->new(
			{   username => $player,
				x        => $SM::Server::clients{$player}->{location}{x},
				y        => $SM::Server::clients{$player}->{location}{y},
			}
		);
		SM::Server->send_packet( $client, $packet->get_raw_data() );
	}

	print Dumper(%SM::Server::clients);
	return 0;

}

# This updates the ::Client object after recieving a AvatarLocation packet
# Also updates all the clients affected (lets them know)
sub update_client_location {
	my ($arg_ref) = @_;
	my $x         = $arg_ref->{x};
	my $y         = $arg_ref->{y};
	my $username  = $arg_ref->{username};

	# Update the client's info
	# It will handle validation in ::Client
	# TODO: Add method to validate in update_location
	my $valid_movement
		= $SM::Server::clients{$username}->update_location( $x, $y );

	# Send all the other users data
	broadcast_location_updates($username);

	return 0;
}

sub broadcast_location_updates {
	my ($username) = @_;

	my $area   = $SM::Server::clients{$username}->get_area();
	my $packet = SM::Server::Packet::Out::Avatar::Location->new(
		{   username => $username,
			x        => $SM::Server::clients{$username}->{location}{x},
			y        => $SM::Server::clients{$username}->{location}{y},
		}
	);

SEND_UPDATE_PACKET:
	foreach my $recipient ( keys %SM::Server::clients ) {
		if ( $recipient eq $username ) {
			next SEND_UPDATE_PACKET;
		}

		# If there are in the same area, send a packet letting the client know
		# of the change
		if ( $SM::Server::clients{$recipient}->get_area() eq $area ) {

			# Send the packet on its merry way
			SM::Server->send_packet( $recipient, $packet->get_raw_data() );
		}
	}
}

sub chat_handle_message {
	my ($arg_ref)     = @_;
	my $reciever_type = $arg_ref->{reciever_type};
	my $sender        = $arg_ref->{sender};
	my $reciever      = $arg_ref->{reciever};
	my $message       = $arg_ref->{message};

	# TODO: Add forged packet stopping code!

	if ( $reciever_type == PRIVMSG ) {
		if ( $sender eq $reciever ) {
			my $packet = $SM::Server::global_chat_server->private_message(
				"It's much more efficient to talk to yourself in real life!",
				"SYSTEM:", $sender );
			SM::Server->send_packet( $sender, $packet->get_raw_data() );
		}
		elsif ( exists $SM::Server::clients{$reciever} ) {
			my $packet
				= $SM::Server::global_chat_server->private_message( $message,
				$sender, $reciever );
			print Dumper($packet);
			SM::Server->send_packet( $reciever, $packet->get_raw_data() );
		}
		else {
			my $packet = $SM::Server::global_chat_server->private_message(
				"User \"$reciever\" does not exist.",
				"SYSTEM:", $sender );
			SM::Server->send_packet( $sender, $packet->get_raw_data() );
		}
	}

	if ( $reciever_type == CHANNEL ) {
		my ( $packet, $clients )
			= $SM::Server::global_chat_server->channel_message( $message,
			$sender, $reciever );

		foreach my $client ( @{$clients} ) {
			SM::Server->send_packet( $client, $packet->get_raw_data() );
		}
	}

	return 0;
}

1;

